package com.eric.seo.onpage;

import java.io.IOException;

import org.jsoup.nodes.Element;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.eric.Config;
import com.eric.seo.SeoPage;

/*0 means fail
1 means pass
2 means warning
3 means info*/
public class OnPageAudit {

	private SeoPage page;

	private int itemsChecked = 0;

	JSONArray resultJA = new JSONArray();

	JSONObject resultJson = new JSONObject();

	public static void main(String[] args) throws IOException {

		SeoPage page = SeoPage.downloadSeoPage("http://www.eelly.com");
		OnPageAudit opa = new OnPageAudit(page);
		opa.inspect();
		System.out.println(opa.resultJA.size());
		// System.out.println(page.avgElementDepth());
	}

	public OnPageAudit(SeoPage page) {
		this.page = page;
	}

	private enum Level {

		VIOLATION("违规"), WARN("警告"), INFO("信息");

		private String name;

		private Level(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}
	}

	public enum CheckItem {
		checkHidden("检查隐藏元素"), checkTitle("检查Title"), checkDescription("检查Meta Description"), checkAlt(
				"检查Alt标签"), checkCanonical("检查Canonical"), checkH("检查H标签"), checkMeta("检查Meta标签"), checkOutLinks(
						"检查出站链接"), checkCSS("检查页面CSS"), checkJS("检查页面JS"), CheckLinks("检查链接");

		private String name;

		private CheckItem(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}

	};

	public JSONObject inspect() {
		int pass = 0;

		if (checkHidden() == 1)
			pass++;
		if (checkTitle() == 1)
			pass++;
		if (checkDescription() == 1)
			pass++;
		if (checkAlt() == 1)
			pass++;
		if (checkCanonical() == 1)
			pass++;
		if (checkH() == 1)
			pass++;
		if (checkMeta() == 1)
			pass++;
		if (checkOutLinks() == 1)
			pass++;
		if (checkCSS() == 1)
			pass++;
		if (checkJS() == 1)
			pass++;
		if (checkLinks() == 1)
			pass++;

		resultJson.put("url", page.url());
		resultJson.put("result", resultJA);
		resultJson.put("checked", itemsChecked);
		resultJson.put("passed", pass);

		return resultJson;
	}

	public int checkHidden() {

		int i = 1;
		for (Element e : page.elements()) {
			if (e.attr("style").contains("display:none") || e.attr("style").contains("visibility:hidden")) {
				resultJA.add(
						new ResultItem(CheckItem.checkHidden.getName(), e.empty(), Level.VIOLATION.getName(), "隐藏元素")
								.json());
				i = 0;
			}
		}
		itemsChecked++;
		return i;
	}

	public int checkTitle() {
		int i = 1;
		String title = page.title();
		if (title.length() < Config.TITLE_LENGTH) {

			resultJA.add(new ResultItem(CheckItem.checkTitle.getName(), page.titleE().toString(), Level.WARN.getName(),
					"标题字符长度过长： " + Config.TITLE_LENGTH).json());
			i = 2;
		} else if (title.equals("")) {
			resultJA.add(new ResultItem(CheckItem.checkTitle.getName(), page.titleE().toString(),
					Level.VIOLATION.getName(), "页面没有标题"));
			i = 0;
		}
		itemsChecked++;
		return i;
	}

	public int checkDescription() {
		int i = 1;
		String desc = page.description();
		if (desc.length() < Config.DESCRIPTION_LENGTH) {
			resultJA.add(new ResultItem(CheckItem.checkDescription.getName(), page.descriptionE().toString(),
					Level.WARN.getName(), "Meta Description字符数太少： " + Config.DESCRIPTION_LENGTH));
			i = 2;
		} else if (desc.equals("")) {
			resultJA.add(new ResultItem(CheckItem.checkDescription.getName(), page.descriptionE().toString(),
					Level.VIOLATION.getName(), "页面没有Meta Description"));
			i = 0;
		}
		itemsChecked++;
		return i;
	}

	public int checkAlt() {
		int i = 1;
		for (Element e : page.images()) {
			if (!e.hasAttr("alt")) {
				resultJA.add(
						new ResultItem(CheckItem.checkAlt.getName(), e.empty(), Level.VIOLATION.getName(), "Alt Text缺失")
								.json());
				i = 0;
			}
		}
		itemsChecked++;
		return i;
	}

	public int checkCanonical() {
		int i = 1;
		if (page.canonical().size() < 1) {
			resultJA.add(new ResultItem(CheckItem.checkCanonical.getName(), page.canonical().toString(),
					Level.VIOLATION.getName(), "Canonical缺失").json());
			i = 0;
		}
		itemsChecked++;
		return i;
	}

	public int checkH() {
		int i = 1;
		int c = 0;
		for (Element e : page.hE()) {
			if (e.tagName().equals("h1"))
				c++;
		}

		if (c < 1) {
			resultJA.add(new ResultItem(CheckItem.checkH.getName(), "", Level.VIOLATION.getName(), "页面没有H1标签").json());
			i = 0;
		} else if (c > 1) {
			resultJA.add(
					new ResultItem(CheckItem.checkH.getName(), "", Level.VIOLATION.getName(), "页面包含多个H1标签").json());
			i = 0;
		}
		itemsChecked++;
		return i;
	}

	public int checkMeta() {
		int i = 1;
		for (Element e : page.meta()) {
			if (e.getElementsByAttributeValue("name", "robots").size() > 0) {
				resultJA.add(new ResultItem(CheckItem.checkMeta.getName(), e.empty().toString(), Level.INFO.getName(),
						"页面有定义Meta Robots").json());
				i = 3;
			}
		}
		itemsChecked++;
		return i;
	}

	public int checkOutLinks() {
		int i = 1;
		if (page.outLinks().size() > Config.OUT_LINKS_LIMIT) {
			resultJA.add(new ResultItem(CheckItem.checkOutLinks.getName(), "", Level.WARN.getName(),
					"出站链接过多： " + Config.OUT_LINKS_LIMIT).json());
			i = 2;
		}
		itemsChecked++;
		return i;
	}

	public int checkLinks() {
		int i = 1;
		for (Element e : page.linkElements()) {
			if (!e.hasAttr("title")) {
				resultJA.add(new ResultItem(CheckItem.CheckLinks.getName(), e.toString(), Level.VIOLATION.getName(),
						"链接没有title属性").json());
				i = 0;
			} else if (e.attr("title").equals("")) {
				resultJA.add(new ResultItem(CheckItem.CheckLinks.getName(), e.toString(), Level.VIOLATION.getName(),
						"链接的title属性为空").json());
				i = 0;
			}
		}
		itemsChecked++;
		return i;
	}

	public int checkCSS() {
		int i = 1;
		if (page.cssCount() > 3) {
			resultJA.add(
					new ResultItem(CheckItem.checkCSS.getName(), "", Level.WARN.getName(), "页面包含3个以上的CSS，考虑用外部文件以及合并")
							.json());
			i = 2;
		}
		itemsChecked++;
		return i;
	}

	public int checkJS() {
		int i = 1;
		if (page.scriptsCount() > 3) {
			resultJA.add(new ResultItem(CheckItem.checkJS.getName(), "", Level.WARN.getName(),
					"页面包含3个以上的JavaScript，考虑用外部文件以及合并").json());
			i = 2;
		}
		itemsChecked++;
		return i;
	}

	/**
	 * 检查页面是否有隐藏元素
	 * 
	 * @return
	 */
	public boolean hiddenElements() {
		if (page.doc().getElementsByAttributeValueMatching("style", "display ?: ?none").empty().size() > 0
				|| page.doc().getElementsByAttributeValueMatching("style", "visibility ?: ?hidden").empty().size() > 0)
			return true;
		else
			return false;
	}
}
